package UMC.Web;

import UMC.Data.IJSON;
import UMC.Data.JSON;
import UMC.Data.Utility;

import java.lang.reflect.Array;
import java.net.URI;
import java.util.Map;

public abstract class UIDialog {

    public interface Action {
        void action(String asyncId);
    }

    public interface Callback {
        UIDialog callback(String asyncId);
    }

    public interface CallForm {
        UIFormDialog callback(String asyncId);
    }

    private static class UIFormValue extends UIFormDialog {

        protected WebMeta InputValue;

        @Override
        protected String type() {
            return null;
        }
    }

    private static class UIDialogValue extends UIDialog {

        protected String InputValue;

        @Override
        protected String type() {
            return null;
        }
    }

    private static class Dialog extends UIDialog {

        public Dialog(String type) {
            this._DType = type;
        }

        String _DType;

        @Override
        protected String type() {
            return _DType;
        }
    }

    public static UIDialog create(String type) {
        UIDialog vDialog = new Dialog(type);
        vDialog.config.put("Undefined", true);
        return vDialog;// new Dialog(type).config("Undefined", true);
    }

    public static UIDialog createImage(String title, URI uri, String tip) {
        Dialog p = new Dialog("Image");
        p.title(title).config.put("Url", uri.toString()).put("Text", tip);
        return p;
    }

    private String _asyncId;

    protected String asyncId() {
        return _asyncId;
    }

    public static UIDialog returnValue(String value) {
        UIDialogValue v = new UIDialogValue();
        v.InputValue = value;// as string;
        return v;

    }

    public static UIFormDialog returnValue(WebMeta value) {
        UIFormValue v = new UIFormValue();

        v.InputValue = value;// as WebMeta;

        return v;

    }

    public static WebMeta asyncDialog(String asyncId, WebContext context, CallForm callback) {

        return asyncValues(context, asyncId, callback);
    }

    /**
     * 对话框类型
     * 
     * @return
     */
    protected abstract String type();

    /**
     * 默认值
     * 
     * @return
     */
    public UIDialog value(String value) {
        config.put("DefaultValue", value);
        return this;
    }

    public UIDialog refreshEvent(String... event) {
        config.put("RefreshEvent", String.join(",", event));
        return this;
    }

    public UIDialog closeEvent(String... event) {
        config.put("CloseEvent", String.join(",", event));
        return this;
    }

    public UIDialog title(String title) {
        config.put("Title", title);
        return this;
    }

    public UIDialog config(String name, String value) {
        config.put(name, value);
        return this;
    }

    public UIDialog config(String name, IJSON value) {
        config.put(name, value);
        return this;
    }

    protected WebMeta config = new WebMeta();

    public static String asyncDialog(WebContext context, String asyncId, Callback callback) {
        return asyncValue(context, asyncId, callback);
    }

    public static final String KEY_DIALOG_ID = "KEY_DIALOG_ID";
    final static String AsyncDialog = "AsyncDialog";

    private static String asyncValue(WebContext context, String asyncId, Callback callback) {

        WebRequest request = context.request();

        String value = request.arguments().get(asyncId);
        if (Utility.isEmpty(value)) {
            value = request.sendValue();
            if (Utility.isEmpty(value)) {
                WebMeta mob = request.sendValues();
                value = Utility.orElse(mob, r -> r.get(asyncId));// mob.get(asyncId);
                if (!Utility.isEmpty(value))
                    mob.remove(asyncId);
            } else {
                Map<String, Object> map = request.headers().map();
                Object v = map.get(request._cmd);

                if (v != null && v.getClass().isArray() && Array.getLength(v) > 1) {
                    int l = Array.getLength(v);
                    String[] vs = new String[l - 1];// Array.newInstance(String.class,l-1);
                    for (int i = 1; i < l; i++)
                        vs[i - 1] = (String) Array.get(v, i);
                    map.put(request._cmd, vs);

                } else {
                    map.remove(request._cmd);
                }
            }

            if (!Utility.isEmpty(value)) {
                request.arguments().put(asyncId, value);
                return value;
            }
            UIDialog dialog = callback.callback(asyncId);
            dialog._asyncId = asyncId;// asyncId();
            if (dialog instanceof UIDialogValue) {
                value = ((UIDialogValue) dialog).InputValue;
                request.arguments().put(asyncId, value);
                return value;
            }

            redirectDialog(request.model(), request.cmd(), dialog, context);
        }
        return value;
    }

    private static WebMeta asyncValues(WebContext context, String asyncId, CallForm callback) {

        WebRequest request = context.request();
        WebMeta rValue = request.arguments().meta(asyncId);
        if (rValue == null) {
            WebMeta sendValue = request.sendValues();
            if (sendValue != null) {
                String value = sendValue.get(asyncId);
                if (!Utility.isEmpty(value) && value.startsWith("{") && value.endsWith("}")) {
                    rValue = JSON.deserialize(value, WebMeta.class);
                    if (rValue != null) {
                        sendValue.remove(asyncId);
                        request.arguments().put(asyncId, value);
                    }
                }
                if (asyncId.equals(sendValue.get(KEY_DIALOG_ID))) {
                    sendValue.remove(KEY_DIALOG_ID);
                    rValue = new WebMeta(sendValue.map());
                    request.headers().remove(request.model());
                }
            }

            if (rValue == null) {
                UIDialog dialog = callback.callback(asyncId);
                dialog._asyncId = asyncId;// ();
                if (dialog instanceof UIFormValue) {
                    rValue = ((UIFormValue) dialog).InputValue;
                    request.arguments().put(asyncId, JSON.serialize(rValue));
                    return rValue;
                }
                redirectDialog(request.model(), request.cmd(), dialog, context);
            } else {
                request.arguments().put(asyncId, JSON.serialize(rValue));
            }
        }
        return rValue;
    }

    protected void initialization(WebContext context) {
    }

    private String _submitText;

    public void submitText(String text) {
        _submitText = text;
    }

    public String submitText() {
        return _submitText;
    }

    protected void initSubmit(WebRequest request) {
        WebMeta p = new WebMeta();
        p.put("send", request.Arguments);
        p.put("model", request._model, "cmd", request._cmd);

        if (!Utility.isEmpty(_submitText)) {
            p.put("text", _submitText);
        }
        this.config.put("Name", this._asyncId);
        this.config.put("Submit", p);
    }

    private static void redirectDialog(String mode, String cmd, UIDialog dialog, WebContext context) {

        dialog.config.put("Type", dialog.type());
        dialog.initSubmit(context.request());

        dialog.initialization(context);
        WebResponse response = context.response();
        response.headers().put(AsyncDialog, dialog.config);

        response.ClientEvent |= WebEvent.ASYNCDIALOG; // | WebEvent.DIALOG;
        response.redirect(mode, cmd, true);

    }

}